<?php
/** 
 * 订单相关
 *
 * @author   xionggan
 * @date     2019-08-07
 */

namespace service;

use think\Db;
use think\Validate;
use think\Exception;
use think\facade\Log;
use service\OrderService;
use service\Distribution;
use service\pay\VirtualPay;
use app\common\model\User;
use app\common\model\CoreOrder;
use app\common\model\CoreOrderPick;
use app\common\model\CoreOrderRebate;
use app\home\model\CouponModel;
use app\home\model\ProductModel;
use app\common\model\Product;
use app\common\model\ProductSelfAddressModel;

class OrderCartService extends OrderService
{

    /**
     * 商品下单结算
     *
     * @param   array   $params     商品数据
     * @return  array   结算数据
     * 参数示例
     * $params => [
     *  'user_id' => 123,
     *  'use_balance' => 1,
     *  'product' => [
     *      ['product_id' => 1, 'number' => 1],
     *      ['product_id' => 2, 'number' => 10],
     *  ],
     *  'coupon' => ['ids' => [1, 2, 3]] or -1,
     * ]
     */
    public function checkCart($params)
    {
        $validate = new Validate($this->getCheckRule());
        $result   = $validate->check($params);

        if (!$result) {
            throw new Exception($validate->getError());
        }

        $user_model     = new User();
        $coupon_model   = new CouponModel();

        $user_data  = $user_model->getOneByUserId($params['user_id']);

        if (empty($user_data)) {
            throw new Exception('用户不存在');
        }

        $product_map = $this->getProductCheck($params['user_id'], $params['product']);

        if (empty($product_map)) {
            throw new Exception('结算失败');
        }

        $result = [
            'product_amount'    => 0,   //订单商品原价总额
            'amount'            => 0,   //订单总额(含邮费，含余额)
            'pay_amount'        => 0,   //订单现金实付总额(含邮费，不含余额)
            'postage'           => 0,   //邮费总额
            'coupon_dis'        => 0,   //优惠券优惠总额
            'member_dis'        => 0,   //自购优惠总额
            'coin_dis'          => 0,   //金币抵扣总额
            'balance_dis'       => 0,   //余额抵扣总额
            'amount_dis'        => 0,   //优惠总额（金币+优惠券+会员优惠）
            'user_balance'      => 0,   //用户账户余额
            'user_coin'         => 0,   //用户账户金币
            'use_balance'       => 0,   //是否使用余额支付
            'coupon_amount'     => 0,   //可使用优惠券商品原价总额
        ];

        foreach ($product_map as $value) {
            $result['product_amount']   = bcadd($result['product_amount'], $value['amount'], 2);
            $result['postage']          = bcadd($result['postage'], $value['postage'], 2);
            $result['member_dis']       = bcadd($result['member_dis'], $value['member_dis'], 2);
            $result['coin_dis']         = bcadd($result['coin_dis'], $value['coin_limit'], 2);

            if ($value['is_benefit'] == 1) {
                $result['coupon_amount'] = bcadd($result['coupon_amount'], $value['amount'], 2);
            }
        }

        if (!empty($params['coupon']['ids'])) {
            $coupon_ids = $params['coupon']['ids'];
        } elseif ($params['coupon'] == -1) {
            $coupon_ids = -1;
        } else {
            $coupon_ids = [];
        }

        $coupon_dis = $coupon_model->couponMoney(
            $params['user_id'], $result['coupon_amount'], $coupon_ids
        );

        $result['use_balance']  = $params['use_balance'];
        $result['user_balance'] = $user_data['user_balance'];
        $result['user_coin']    = $user_data['user_gold'];
        
        $result['coupon_dis']   = $coupon_dis['count_money'] ?? 0;
        $result['coupon_dis']   = bcsub($result['coupon_dis'], 0, 2);
        $result['coupon_dis']   = min($result['coupon_dis'], bcsub($result['product_amount'], $result['member_dis'], 2));  
        $result['pay_amount']   = bcsub($result['product_amount'], $result['member_dis'], 2);
        $result['pay_amount']   = bcsub($result['pay_amount'], $result['coupon_dis'], 2);

        if ($result['pay_amount'] > 0) {
            if ($result['pay_amount'] > $result['coin_dis']) {
                $result['coin_dis'] = $result['coin_dis'];
            } else {
                $result['coin_dis'] = $result['pay_amount'];
            }

            if ($user_data['user_gold'] > $result['coin_dis']) {
                $result['coin_dis'] = $result['coin_dis'];
            } else {
                $result['coin_dis'] = $user_data['user_gold'];
            }
        } else {
            $result['coin_dis'] = 0;
        }

        $result['pay_amount']   = bcsub($result['pay_amount'], $result['coin_dis'], 2);
        $result['pay_amount']   = $result['pay_amount'] < 0 ? 0 : $result['pay_amount'];
        $result['pay_amount']   = bcadd($result['pay_amount'], $result['postage'], 2);

        $result['amount']       = $result['pay_amount'];
        $result['amount_dis']   = bcadd($result['coupon_dis'], $result['coin_dis'], 2);
        $result['amount_dis']   = bcadd($result['amount_dis'], $result['member_dis'], 2);

        $result['product']      = $product_map;
        $result['coupon']       = [
            'be_use'    => $coupon_dis['be_use'] ?? [], 
            'can_use'   => $coupon_dis['can_use'] ?? [],
        ];

        if ($params['use_balance'] == 1) {
            $result['balance_dis'] = $result['user_balance'] > $result['pay_amount'] 
                ? $result['pay_amount'] : $result['user_balance'];
            $result['pay_amount'] = bcsub($result['pay_amount'], $result['balance_dis'], 2);
        }

        $result = $this->getProductCheck2($result); //商品金币
        $result = $this->getProductCheck4($result); //商品优惠券
        $result = $this->getProductCheck3($result); //商品实付
        $result = $this->getProductCheck5($result); //商品余额

        return $result;
    }

    /**
     * 创建商品订单
     *
     * @param   array   $params 商品数据，同结算方法
     * @return  string  订单号
     * 参数示例
     * $params => [
     *  'user_id' => 123,
     *  'self_point'    => 1,
     *  'self_name'     => '李三',
     *  'self_phone'    => '133',
     *  'user_address'  => 1,
     *  'use_balance' => 1,
     *  'product' => [
     *      ['product_id' => 1, 'number' => 1],
     *      ['product_id' => 2, 'number' => 10],
     *  ],
     *  'coupon' => ['ids' => [1, 2, 3]],
     * ]
     */
    public function createOrder($params)
    {
        $validate = new Validate($this->getOrderRule());
        $result   = $validate->check($params);

        if (!$result) {
            throw new Exception($validate->getError());
        }

        $user_model = new User();
        $user_data  = $user_model->getOneByUserId($params['user_id']);

        if (empty($user_data)) {
            throw new Exception('用户不存在');
        }

        $product_model  = new Product();
        $coupon_model   = new CouponModel();
        $check_data     = $this->checkCart($params);

        if ($check_data['coupon_dis'] > 0 && empty($params['coupon']['ids'])) {
            throw new Exception('优惠券异常');
        }

        $check_data     = $this->getProductData($user_data['user_id'], $check_data);
        $order_product  = $this->getOrderProduct($check_data);
        $order_data     = $this->getOrderData($user_data, $check_data, $order_product, $params);
        $order_group    = $this->getOrderBreak($order_data);
        $order_group    = $this->getOrderRebate($order_group);

        Db::startTrans();

        try {
            $this->setType('GW');
            $parent_order = '';
            
            foreach ($order_group as $value) {
                $product    = $value['product'];
                $rebate     = $value['rebate'];

                unset($value['product']);
                unset($value['rebate']);

                foreach ($product as $val) {
                    $product_model->stockUpdate($val['product_id'], $val['number']);
                    $this->addProduct($val);
                }

                foreach ($rebate as $val) {
                    $this->addProductRebate($val);
                }

                if (!empty($parent_order)) {
                    $value['display']       = 0;
                    $value['parent_order']  = $parent_order;
                    $order_sn = $this->create($value);
                } else {
                    $value['coupon_ids'] = implode(',', $params['coupon']['ids'] ?? []);
                    $order_sn = $this->create($value);
                    $parent_order = $order_sn;
                }

                $this->setAction($order_sn, [
                    'can_pay'       => 1,
                    'can_cancel'    => 1,
                    'can_detail'    => 1,
                ]);
            }

            if (!empty($params['coupon']['ids'])) {
                $coupon_model->couponCheck($params['coupon']['ids']);
            }
            
        } catch (Exception $e) {
            Db::rollback();
            Log::write('购物车结算生成订单失败: ' . $e->getMessage(), 'error');
            throw new Exception($e->getMessage());
        }

        Db::commit();

        return $parent_order;
    }

    /**
     * 支付完成商品订单
     *
     * @param   string  $order_sn       支付订单号
     * @param   array   $update_data    更新的数据，参考OrderService中update方法
     * @return  boole
     */
    public function payedOrder($order_sn, $update_data)
    {
        $order_model    = new CoreOrder();
        $rebate_model   = new CoreOrderRebate();
        $virtual_pay    = new VirtualPay();
        $parent_data    = $order_model->getOneBySn($order_sn);

        if (empty($parent_data)) {
            return false;
        }

        $parent_data = $parent_data->toArray();

        if ($parent_data['status'] != CoreOrder::STATUS_0) {
            return false;
        }

        $son_order = $order_model->getAllByParentSn($order_sn);

        if (!$son_order->isEmpty()) {
            $son_order = $son_order->toArray();
        } else {
            $son_order = [];
        }

        $order_data = array_merge([$parent_data], $son_order);

        Db::startTrans();

        try {
            if (
                (!empty($update_data['balance']) && 
                $update_data['balance'] != (int)($order_data[0]['balance'] * 100)) || 
                (!empty($update_data['gold_coin']) && 
                $update_data['gold_coin'] != (int)($order_data[0]['gold_coin'] * 100))
            ) {
                $update_data = $this->updateOrderRecheck($order_data, $update_data);
                //余额、金币发生变动
                $this->updateOrder2($order_data, $update_data);
            } else {
                //余额、金币没有变动
                $this->updateOrder($order_data, $update_data);
            }
        } catch (Exception $e) {
            Db::rollback();
            Log::write('购物车结算支付完成订单失败: ' . $e->getMessage() . date('Y-m-d H:i:s'), 'error');
            throw new Exception($e->getMessage());
        }

        Db::commit();

        $rebate_data = $rebate_model->getAllByOrderId($parent_data['order_id']);

        if (empty($rebate_data)) {
            return true;
        }

        foreach ($rebate_data as $value) {
            $rebate_balance = bcdiv($value['rebate_balance'], 100, 2);
            $rebate_coin    = bcdiv($value['rebate_coin'], 100, 2);
            $virtual_pay->public_update_user_lockvirtual(
                $value['user_id'], 0, 1, 3, $rebate_balance, $rebate_coin, 
                0, $value['rebate_id'], $value['remark'], 2//, $value['order_sn']
            );
        }
    }

    /**
     * 商品下单结算-商品价格分算
     * 
     */
    protected function getProductCheck($user_id, $products)
    {
        $product_model  = new ProductModel();
        $distribution   = new Distribution();

        foreach ($products as $key => $value) {
            $product_data = $product_model->checkProduct(
                $user_id, $value['product_id'], $value['number'], false
            );

            if ($product_data == false) {
               throw new Exception($product_model->getError()); 
            }

            $grade_price = $distribution->getGradePrice($user_id, 1, $value['product_id']);
            if ($grade_price < 0) {
                $grade_price = $product_data['product_price'];
            }

            if ($grade_price < $product_data['product_coin']) {
                $product_data['product_coin'] = $grade_price;
            }

            $product_map[] = array_merge($value, [
                'price'         => $product_data['product_price'],
                'amount'        => bcmul($product_data['product_price'], $value['number'], 2),
                'member_price'  => $grade_price,
                'member_dis'    => bcmul(
                    bcsub($product_data['product_price'], $grade_price, 2), 
                    $value['number'], 
                    2
                ),
                'coin_limit'    => bcmul($product_data['product_coin'], $value['number'], 2),
                'postage'       => $product_data['dispatching_type'] == 1 ? $product_data['product_postage'] : 0,
                'is_benefit'    => $product_data['is_benefit'],
            ]);
        }

        return $product_map ?? [];     
    }

    /**
     * 商品下单结算-商品金币分算
     *
     */
    protected function getProductCheck2($data)
    {
        $coin_dis_sum = $coin_dis_num = $coin_dis_all = 0;

        foreach ($data['product'] as $value) {
            if ($value['coin_limit'] <= 0) {
                continue;
            }

            $coin_dis_num += 1;
            $coin_dis_sum += bcmul($value['coin_limit'], $value['number'], 2);
        }

        foreach ($data['product'] as $key => $value) {
            if ($value['coin_limit'] <= 0) {
                $data['product'][$key]['coin_dis'] = 0;
                continue;
            }

            if ($coin_dis_sum == 0) {
                $data['product'][$key]['coin_dis'] = 0;
            } elseif ($coin_dis_sum == $data['coin_dis']) {
                $data['product'][$key]['coin_dis'] = bcmul($value['coin_limit'], $value['number'], 2);
            } elseif (--$coin_dis_num == 0) {
                if ($data['coin_dis'] > $coin_dis_all) {
                    $data['product'][$key]['coin_dis'] = bcsub($data['coin_dis'], $coin_dis_all, 2);
                } else {
                    $data['product'][$key]['coin_dis'] = $data['coin_dis'];
                }
            } else {
                $coin_dis = bcmul(
                    $data['coin_dis'], 
                    bcdiv(
                        bcmul($value['coin_limit'], $value['number'], 2), $coin_dis_sum, 8
                    ), 2
                );
                $data['product'][$key]['coin_dis'] = $coin_dis;
                $coin_dis_all += $coin_dis;
            }
        }

        return $data;
    }

    /**
     * 商品下单结算-商品实付分算
     *
     */
    protected function getProductCheck3($data)
    {
        $amount_sum = 0;
        foreach ($data['product'] as $key => $value) {
            $sum_pro = bcmul($value['member_price'], $value['number'], 2);

            if ($sum_pro > $value['coin_dis']) {
                $sum_pro = bcsub($sum_pro, $value['coin_dis'], 2);
            } else {
                $sum_pro = 0.00;
            }

            if ($sum_pro > $value['coupon_dis']) {
                $sum_pro = bcsub($sum_pro, $value['coupon_dis'], 2);
            } else {
                $sum_pro = 0.00;
            }

            $sum_pro    = bcadd($sum_pro, $value['postage'], 2);
            $amount_sum = bcadd($amount_sum, $sum_pro, 2);
            $data['product'][$key]['pay_amount'] = $sum_pro;
        }

        return $data;
    }

    /**
     * 商品下单结算-优惠券分算
     *
     */
    protected function getProductCheck4($data)
    {
        $coupon_sum = 0;

        foreach ($data['product'] as $key => $value) {
            if (
                $data['coupon_amount'] <= 0 || 
                $value['price'] <= 0 || 
                $value['is_benefit'] == 0
            ) {
                $data['product'][$key]['coupon_dis'] = 0;
                continue;
            }

            if (count($data['product']) == ($key + 1)) {
                $data['product'][$key]['coupon_dis'] = bcsub($data['coupon_dis'], $coupon_sum, 2);
            } else {
                $data['product'][$key]['coupon_dis'] = bcmul(
                    bcdiv(bcmul($value['price'], $value['number'], 2), $data['coupon_amount'], 8), $data['coupon_dis'], 2
                );
                $coupon_sum += $data['product'][$key]['coupon_dis'];          
            }
        }        

        return $data;
    }

    /**
     * 商品下单结算-商品余额分算
     *
     */
    protected function getProductCheck5($data)
    {
        $balance_sum = $pay_amount = 0;
        foreach ($data['product'] as $key => $value) {
            if ($data['balance_dis'] <= 0) {
                $data['product'][$key]['balance_dis'] = 0;
                continue; 
            }

            $pay_amount = bcadd($data['pay_amount'], $data['balance_dis'], 2);

            if ($pay_amount <= 0) {
                $data['product'][$key]['balance_dis'] = 0;
                continue;
            }

            if (count($data['product']) == ($key + 1)) {
                $tmp = bcsub($data['balance_dis'], $balance_sum, 2);
                $data['product'][$key]['balance_dis'] = $tmp > 0 ? $tmp : 0; 
            } else {
                $data['product'][$key]['balance_dis'] = bcmul(
                    bcdiv($value['pay_amount'], $pay_amount, 8), $data['balance_dis'], 2
                );
                $balance_sum += $data['product'][$key]['balance_dis'];          
            } 
        }

        return $data;
    }

    /**
     * 生成订单-获取商品数据
     *
     */
    protected function getProductData($user_id, $data)
    {
        $product_model = new ProductModel();
        $products = $data['product'];

        foreach ($products as $key => $value) {
            $product_data = $product_model->checkProduct(
                $user_id, $value['product_id'], $value['number']
            );

            if ($product_data == false) {
               throw new Exception($product_model->getError()); 
            }

            $products[$key]['shipping_type'] = $product_data['dispatching_type'] == 1 ? 1 : 2;
            $products[$key]['product_data'] = $product_data;
            $shipping_type[$products[$key]['shipping_type']][] = $product_data['product_id'];
        }

        $data['shipping_type'] = $shipping_type;
        $data['product'] = $products;

        return $data;     
    }

    /**
     * 生成订单-获取订单商品数据
     *
     */
    protected function getOrderProduct($data)
    {
        foreach ($data['product'] as $value) {
            $postage = $value['product_data']['dispatching_type'] == 1 ? 
                        $value['product_data']['product_postage'] : 
                        0;
            $amount = bcsub($value['amount'], $value['member_dis'], 2);
            $amount = bcadd($amount, $postage, 2);
            $amount_product = bcmul($value['product_data']['product_price'], 100);
            $amount_product = bcmul($amount_product, $value['number']);

            $order_product[$value['shipping_type']][] = [
                'store_id'          => '0',  
                'product_id'        => $value['product_data']['product_id'],  
                'product_name'      => $value['product_data']['product_name'],  
                'product_img'       => $value['product_data']['product_image'],  
                'number'            => $value['number'],  
                'price'             => $value['price'] * 100,
                'amount'            => $amount * 100,
                'amount_product'    => $amount_product,
                'data_id'           => '0',
                'price_origin'      => $value['product_data']['product_ot_price'] * 100,
                'balance'           => $value['balance_dis'] * 100,
                'gold_coin'         => $value['coin_dis'] * 100,
                'amount_pay'        => $value['pay_amount'] * 100,
                'member_dis'        => $value['member_dis'] * 100,
                'coupon_dis'        => $value['coupon_dis'] * 100,
                'shipping_type'     => $value['shipping_type'],
                'close_time'        => $value['product_data']['product_end_time'],
                'postage'           => $postage * 100 ,
                'exdelivery_time'   => $value['shipping_type'] == 1 
                    ? strtotime('+ ' . $value['product_data']['after_order_delivery'] . ' day', time())
                    : $value['product_data']['delivery_time'],
            ];
        }

        return $order_product;
    }

    /**
     * 生成订单-生成订单数据
     *
     */
    protected function getOrderData($user_data, $check_data, $order_product, $params)
    {
        $self_model = new ProductSelfAddressModel();

        foreach ($order_product as $shipping_type => $value) {
            $amount     = bcadd($check_data['coin_dis'], $check_data['balance_dis'], 2);
            $amount     = bcadd($amount, $check_data['pay_amount'], 2);
            $amount_dis = bcadd($check_data['coin_dis'], $check_data['coupon_dis'], 2);
            $amount_dis = bcadd($amount_dis, $check_data['member_dis'], 2);
            $amount_pay = bcadd($check_data['pay_amount'], $check_data['balance_dis'], 2);

            $order_data = [
                'user_id'           => $user_data['user_id'], 
                'balance'           => $check_data['balance_dis'] * 100,  
                'gold_coin'         => $check_data['coin_dis'] * 100,
                'postage'           => $check_data['postage'] * 100,
                'amount'            => $amount * 100,
                'amount_product'    => $check_data['product_amount'] * 100,
                'amount_dis'        => $amount_dis * 100,  
                'amount_pay'        => $amount_pay * 100,  
                'member_dis'        => $check_data['member_dis'] * 100,  
                'coin_dis'          => $check_data['coin_dis'] * 100,  
                'coupon_dis'        => $check_data['coupon_dis'] * 100,   
                'display'           => 1, 
                'use_balance'       => $check_data['use_balance'] == 1 ? 1 : 0,
            ];

            if ($shipping_type == 1) {
                $order_data['store_id']     = 0;
                $order_data['self']         = 0;
                $order_data['self_point']   = $params['user_address'] ?? 0;
            } elseif ($shipping_type == 2) {
                $self_data = $self_model->getOneByPK($params['self_point'] ?? 0);
                $order_data['self']         = 1;
                $order_data['store_id']     = $self_data['merchant_id'] ?? 0;
                $order_data['self_point']   = $self_data['self_address_id'] ?? 0;
                $order_data['self_name']    = $params['self_name'] ?? '';
                $order_data['self_phone']   = $params['self_phone'] ?? '';
            }

            $order_data['product'] = $value;
            $result[] = $order_data;
        }

        return $result;    
    }

    /**
     * 生成订单-拆单
     *
     */
    protected function getOrderBreak($data)
    {
        if (count($data) == 1) {
            return $data;
        }

        foreach ($data as $value) {
            $child = $value;
            $child['balance']           = 0;
            $child['gold_coin']         = 0;
            $child['postage']           = 0;
            $child['amount']            = 0;
            $child['amount_dis']        = 0;
            $child['amount_product']    = 0;
            $child['amount_pay']        = 0;
            $child['member_dis']        = 0;
            $child['coin_dis']          = 0;
            $child['coupon_dis']        = 0;

            foreach ($value['product'] as $val) {
                $amount_dis = $val['gold_coin'] + $val['member_dis'];
                $amount_dis = $amount_dis + $val['coupon_dis']; 
                $child['balance']           += $val['balance'];
                $child['gold_coin']         += $val['gold_coin'];
                $child['postage']           += $val['postage'];
                $child['amount']            += $val['amount'];
                $child['amount_product']    += $val['amount_product'];
                $child['amount_dis']        += $amount_dis;
                $child['amount_pay']        += $val['amount_pay'];
                $child['member_dis']        += $val['member_dis'];
                $child['coin_dis']          += $val['gold_coin'];
                $child['coupon_dis']        += $val['coupon_dis'];
            }

            $child_data[] = $child;
        }

        $parent_order = array_shift($data);

        foreach ($data as $value) {
            foreach ($value['product'] as $val) {
                $parent_product[] = $val;
            }
        }

        $parent_order['product'] = array_merge(
            $parent_order['product'], $parent_product
        );

        return array_merge([$parent_order], $child_data);
    }

    /**
     * 生成订单-计算返利
     *
     */
    protected function getOrderRebate($data)
    {
        $user_model     = new User();
        $distri_service = new Distribution();
        $distri_data    = [];

        foreach ($data as $key => $value) {
            $data[$key]['rebate'] = [];

            foreach ($value['product'] as $val) {
                $pmap[$val['product_id']] = $val['product_name'];
                $pids[] = [
                    'foreign_id'    => $val['product_id'], 
                    'order_sum'     => bcdiv(bcsub($val['amount'], $val['postage']), 100, 2),
                ];
            }

            $rebate     = $distri_service->get_distribution_money_product($value['user_id'], 1, $pids);
            $user_data  = $user_model->getOneByUserId($value['user_id']);
            
            if (empty($rebate)) {
                continue;
            }

            foreach ($rebate as $v) {
                if ($v['rebate_balance'] <= 0 && $v['rebate_coin'] <= 0) {
                    continue; 
                }

                $pro_name   = $pmap[$v['foreign_id']] ?? '';
                $remark     = ($user_data['user_nickname'] ?? '粉丝').'，购买 '.$pro_name.' 返';
                $data[$key]['rebate'][] = [
                    'user_id'           => $v['top_user_id'],
                    'level'             => $v['level'],
                    'product_id'        => $v['foreign_id'],
                    'product_name'      => $pro_name,
                    'number'            => $val['number'],
                    'price'             => $val['price'],
                    'amount'            => bcsub($val['amount'], $val['postage']),
                    'rebate_balance'    => $v['rebate_balance'] * 100,
                    'rebate_coin'       => $v['rebate_coin'] * 100,
                    'remark'            => $remark,
                ];
            }
        }
        
        return $data;
    }

    /**
     * 支付完成商品订单-更新订单数据(余额、金币没有变动)
     *
     */
    protected function updateOrder($order_data, $update_data)
    {
        unset($update_data['balance']);
        unset($update_data['gold_coin']);

        foreach ($order_data as $value) {
            $this->setOrderPaid($value['order_sn']);

            if (count($order_data) > 1) {
                if (!empty($value['parent_order'])) {
                    $update_data['display'] = CoreOrder::DISPLAY_1;
                    unset($update_data['status']);
                } else {
                    $update_data['display'] = CoreOrder::DISPLAY_0;
                    $update_data['status']  = CoreOrder::STATUS_11;
                }                  
            }
            
            $this->update($value['order_sn'], $update_data);
            $this->setAction($value['order_sn'], [
                'can_refund'    => 1,
                'can_detail'    => 1,
            ]);
        }
    }

    /**
     * 支付完成商品订单-更新订单数据(余额、金币发生变动)
     *
     */
    protected function updateOrder2($order_data, $update_data)
    {
        $order_change = $update_data['order'] ?? [];
        unset($update_data['order']);

        foreach ($order_data as $value) {
            $pay_data = [];
            $this->setOrderPaid($value['order_sn']);

            if (count($order_data) > 1) {
                if (!empty($value['parent_order'])) {
                    $update_data['display'] = CoreOrder::DISPLAY_1;
                    unset($update_data['status']);
                } else {
                    $update_data['display'] = CoreOrder::DISPLAY_0;
                    $update_data['status']  = CoreOrder::STATUS_11;
                } 
            }

            if (isset($order_change[$value['order_sn']]['balance'])) {
                $pay_data['balance'] = $order_change[$value['order_sn']]['balance'];
            }

            if (isset($order_change[$value['order_sn']]['gold_coin'])) {
                $pay_data['gold_coin'] = $order_change[$value['order_sn']]['gold_coin'];
            }

            !empty($pay_data) && $update_data = array_merge($update_data, $pay_data);

            foreach ($value['product'] as $val) {
                $pay_data2 = [];
                if (isset($order_change[$value['order_sn']]['product'][$val['order_pid']]['balance'])) {
                    $pay_data2['balance'] = $order_change[$value['order_sn']]['product'][$val['order_pid']]['balance'];
                }

                if (isset($order_change[$value['order_sn']]['product'][$val['order_pid']]['gold_coin'])) {
                    $pay_data2['gold_coin'] = $order_change[$value['order_sn']]['product'][$val['order_pid']]['gold_coin'];
                }

                !empty($pay_data2) && $this->updateProduct($val['order_pid'], $pay_data2);
            }

            $this->update($value['order_sn'], $update_data);
            $this->setAction($value['order_sn'], [
                'can_refund'    => 1,
                'can_detail'    => 1,
            ]);
        }
    }

    /**
     * 支付完成商品订单-余额、金币变动，重新计算商品分布量
     *
     */
    protected function updateOrderRecheck($order_data, $update_data)
    {   
        $new_balance    = $update_data['balance'];
        $old_balance    = $order_data[0]['balance'] * 100;
        $new_coin       = $update_data['gold_coin'];
        $old_coin       = $order_data[0]['gold_coin'] * 100;
        $balance_rate   = $old_balance > 0 ? bcdiv($new_balance, $old_balance, 8) : 1;
        $coin_rate      = $old_coin > 0 ? bcdiv($new_coin, $old_coin, 8) : 1;

        foreach ($order_data as $value) {
            if (empty($value['parent_order'])) {
                $balance    = $new_balance;
                $gold_coin  = $new_coin;
            } else {
                $balance    = round(bcmul($value['balance'] * 100, $balance_rate, 2));
                $gold_coin  = round(bcmul($value['gold_coin'] * 100, $coin_rate, 2));         
            }

            $update_data['order'][$value['order_sn']]['balance']    = $balance;
            $update_data['order'][$value['order_sn']]['gold_coin']  = $gold_coin; 

            foreach ($value['product'] as $val) {
                $balance_p    = round(bcmul($val['balance'], $balance_rate, 2));
                $gold_coin_p  = round(bcmul($val['gold_coin'], $coin_rate, 2));  
                $update_data['order'][$value['order_sn']]['product'][$val['order_pid']]['balance'] = $balance_p * 100;
                $update_data['order'][$value['order_sn']]['product'][$val['order_pid']]['gold_coin'] = $gold_coin_p * 100;        
            }

        }
        return $update_data;
    }

    /**
     * 商品下单结算-参数验证
     *
     */
    protected function getCheckRule()
    {
        return [
            'user_id' => function ($value, $data) {
                if (empty($value) || (int) $value < 1) {
                    return 'user_id 不能为空或格式错误';
                }
                return true;
            },
            'use_balance' => function ($value, $data) {
                if (!isset($value) || !in_array($value, [0, 1])) {
                    return 'use_balance 格式错误，只能为0或1';
                }
                return true;
            },
            'product' => function ($value, $data) {
                if (!is_array($value)) {
                    return '参数 product 必须是数组';
                }
                if (empty($value)) {
                    return '参数 product 不能为空';
                }
                foreach ($value as $val) {
                    if (empty($val['product_id'])) {
                        return '商品 product_id 不能为空';
                    }
                    if (empty($val['number']) || (int) $val['number'] < 1) {
                        return '商品 number 必须为大于等于1的整数';
                    }                    
                }
                return true;
            },
            'coupon' => function ($value, $data) {
                // if (!isset($value) || empty($value)) {
                //     return true;
                // }
                // if (!is_array($value)) {
                //     return '参数 coupon 必须是数组';
                // }
                // if (!isset($value['ids'])) {
                //     return '优惠券 ids 不能为空';
                // }
                return true;        
            },
        ];        
    }

    /**
     * 商品下单结算-参数验证
     *
     */
    protected function getOrderRule()
    {
        return array_merge([
            'user_id' => function ($value, $data) {
                if (empty($user_id)) {
                    return 'user_id 格式错误';
                }
                return true;
            }, 
            'self_point' => function ($value, $data) {
                if (!empty($value) && (int) $value < 1) {
                    return 'self_point 格式错误';
                }
                return true;
            }, 
            'self_name' => function ($value, $data) {
                if (!empty($data['self_point']) && empty($value)) {
                    return 'self_name 不能为空';
                }
                return true;
            },     
            'self_phone' => function ($value, $data) {
                if (!empty($data['self_point']) && empty($value)) {
                    return 'self_phone 不能为空';
                }
                return true;
            },    
            'user_address' => function ($value, $data) {
                if (!empty($value) && (int) $value < 1) {
                    return 'user_address 格式错误';
                }
                return true;
            },    
        ], $this->getCheckRule());
    }

}
